package com.umeox.watch.moto.dataservice.mqtt;

import android.text.TextUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.umeox.moto.common.log.Logger;
import com.umeox.moto.mqtt.event.IOnPushListener;
import com.umeox.moto.mqtt.event.PersistentEventDispatcher;
import com.umeox.watch.moto.apiclient.model.DeviceCodeDTO;
import com.umeox.watch.moto.apiclient.model.WifiDTO;
import com.umeox.watch.moto.dataservice.base.BaseApp;
import com.umeox.watch.moto.dataservice.constants.InternalConstant;
import com.umeox.watch.moto.dataservice.constants.MqttConstants;
import com.umeox.watch.moto.dataservice.mqtt.rpc.PushMsgRpc;
import com.umeox.watch.moto.dataservice.mqtt.rpc.ResponseRpc;
import com.umeox.watch.moto.dataservice.utils.GuavaCacheUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Created by Rambo 2020/5/1
 * Describe:只处理服务器主动推送的消息，对于客户端rpc响应回复，客户端事件上传回复等消息不做处理
 */
public class MessageCenter implements IOnPushListener {
    private static final String TAG = "MessageCenter";
    private volatile static MessageCenter instance;

    private DeviceSecretRegisterListener mDeviceSecretRegisterListener;

    private MessageCenter() {

    }

    public static MessageCenter getInstance() {
        if (instance == null) {
            synchronized (MessageCenter.class) {
                if (instance == null) {
                    instance = new MessageCenter();
                }
            }
        }
        return instance;
    }

    public void init(DeviceSecretRegisterListener listener) {
        PersistentEventDispatcher.getInstance().registerOnPushListener(this, true);
        mDeviceSecretRegisterListener = listener;
    }

    public void detach() {
        PersistentEventDispatcher.getInstance().unregisterOnPushListener(this);
    }

    @Override
    public void onCommand(String topic, byte[] payload) {
        Logger.i("MessageCenter topic:" + topic + ",message:" + new String(payload));
        JSONObject jsonObject = JSONObject.parseObject(new String(payload));
        if (jsonObject.containsKey("error")) {
            return;
        }

        if (topic.equals(Topic.AUTH_TOPIC)) {
            PayloadMessage payloadMessage = PayloadMessage.convertAttributesPM(topic, payload);
            String deviceSecret = (String) payloadMessage.getProperty("deviceSecret");
            if (!TextUtils.isEmpty(deviceSecret)) {
                BaseApp.getInstance().getMmkv().encode(InternalConstant.KEY_DEVICE_SECRET, deviceSecret);
                if (mDeviceSecretRegisterListener != null) {
                    mDeviceSecretRegisterListener.onDeviceSecretRegistered();
                }
            } else {
                Logger.i("deviceSecret is NULL or Empty");
            }

        } else if (topic.equals(Topic.DEVICE_ATTRIBUTES_TOPIC)) {//云端下发属性
            PayloadMessage payloadMessage = PayloadMessage.convertAttributesPM(topic, payload);
            HashMap<String, Object> hashMap = payloadMessage.getPropertys();
            for (Map.Entry<String, Object> stringObjectEntry : hashMap.entrySet()) {
                String key = stringObjectEntry.getKey();
                Logger.e("key:" + key);
            }
            if (payloadMessage.hasProperty(MqttConstants.Attributes.HOT_VER)) {
                Logger.i("收到共享属性版本号更改消息");
                //共享属性版本号
                JSONObject versionJsonObject = (JSONObject) payloadMessage.getProperty(MqttConstants.Attributes.HOT_VER);
                DataHandleManager.getInstance().updateLocalVersion(versionJsonObject);
            }
            if (payloadMessage.hasProperty(MqttConstants.Attributes.DEVICE_CONFIG)) {
                Logger.i("收到设备信息更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.DEVICE_CONFIG, payloadMessage);
            }
            if (payloadMessage.hasProperty(MqttConstants.Attributes.LOCATION_FREQ)) {
                Logger.i("收到定位时段更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.LOCATION_FREQ, payloadMessage);
            }
            if (payloadMessage.hasProperty(MqttConstants.Attributes.CONTACTS)) {
                Logger.i("收到联系人信息更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.CONTACTS, payloadMessage);
            }
            if (payloadMessage.hasProperty(MqttConstants.Attributes.HOLDER_INFO)) {
                Logger.i("收到HolderInfo更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.HOLDER_INFO, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.FRIENDS)) {
                Logger.i("收到Friends更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.FRIENDS, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.IM_GROUP)) {
                Logger.i("收到IMGroup更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.IM_GROUP, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.ALARM)) {
                Logger.i("收到Alarm更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.ALARM, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.CLASS_MODE)) {
                Logger.i("收到ClassMode更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.CLASS_MODE, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.WIFI_CONFIG)) {
                Logger.i("收到WifiConfig更改消息");
                JSONArray jsonArray = (JSONArray) payloadMessage.getProperty(MqttConstants.Attributes.WIFI_CONFIG);
                String jsonStr = JSONObject.toJSONString(jsonArray);
                List<WifiDTO> wifiDTOList = JSONObject.parseArray(jsonStr, WifiDTO.class);
                DataHandleManager.getInstance().configWifi(wifiDTOList);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.FENCES)) {
                Logger.i("收到Fences更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.FENCES, payloadMessage);
            }


            if (payloadMessage.hasProperty(MqttConstants.Attributes.SPORT_CHALLENGE)) {
                Logger.i("收到sportChallenge更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.SPORT_CHALLENGE, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.PRAYER_SETTING)) {
                Logger.i("收到prayerSetting更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.PRAYER_SETTING, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.QURAN_LEARN)) {
                Logger.i("收到quranLearnChallenge更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.QURAN_LEARN, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.TASKS)) {
                Logger.i("收到tasks更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.TASKS, payloadMessage);
            }

        } else if (topic.startsWith(Topic.ATTRIBUTE_RESPONSE_PREFIX)) { //获取属性,云端回复
            PayloadMessage payloadMessage = PayloadMessage.convertAttributePM(topic, payload);
            HashMap<String, Object> hashMap = payloadMessage.getPropertys();
            for (Map.Entry<String, Object> stringObjectEntry : hashMap.entrySet()) {
                String key = stringObjectEntry.getKey();
                Logger.e("key:" + key);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.HOT_VER)) {
                Logger.i("收到共享属性版本号更改消息");
                //共享属性版本号
                JSONObject versionJsonObject = (JSONObject) payloadMessage.getProperty(MqttConstants.Attributes.HOT_VER);
                DataHandleManager.getInstance().updateLocalVersion(versionJsonObject);
            }
            if (payloadMessage.hasProperty(MqttConstants.Attributes.DEVICE_CONFIG)) {
                Logger.i("收到设备信息更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.DEVICE_CONFIG, payloadMessage);
            }
            if (payloadMessage.hasProperty(MqttConstants.Attributes.LOCATION_FREQ)) {
                Logger.i("收到定位时段更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.LOCATION_FREQ, payloadMessage);
            }
            if (payloadMessage.hasProperty(MqttConstants.Attributes.CONTACTS)) {
                Logger.i("收到联系人信息更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.CONTACTS, payloadMessage);
            }
            if (payloadMessage.hasProperty(MqttConstants.Attributes.HOLDER_INFO)) {
                Logger.i("收到HolderInfo更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.HOLDER_INFO, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.FRIENDS)) {
                Logger.i("收到Friends更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.FRIENDS, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.IM_GROUP)) {
                Logger.i("收到IMGroup更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.IM_GROUP, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.ALARM)) {
                Logger.i("收到Alarm更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.ALARM, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.CLASS_MODE)) {
                Logger.i("收到ClassMode更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.CLASS_MODE, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.WIFI_CONFIG)) {
                Logger.i("收到WifiConfig更改消息");
                JSONArray jsonArray = (JSONArray) payloadMessage.getProperty(MqttConstants.Attributes.WIFI_CONFIG);
                String jsonStr = JSONObject.toJSONString(jsonArray);
                List<WifiDTO> wifiDTOList = JSONObject.parseArray(jsonStr, WifiDTO.class);
                DataHandleManager.getInstance().configWifi(wifiDTOList);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.FENCES)) {
                Logger.i("收到Fences更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.FENCES, payloadMessage);
            }


            if (payloadMessage.hasProperty(MqttConstants.Attributes.SPORT_CHALLENGE)) {
                Logger.i("收到sportChallenge更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.SPORT_CHALLENGE, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.PRAYER_SETTING)) {
                Logger.i("收到prayerSetting更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.PRAYER_SETTING, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.QURAN_LEARN)) {
                Logger.i("收到quranLearnChallenge更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.QURAN_LEARN, payloadMessage);
            }

            if (payloadMessage.hasProperty(MqttConstants.Attributes.TASKS)) {
                Logger.i("收到tasks更改消息");
                DataHandleManager.getInstance().updateData(MqttConstants.Attributes.TASKS, payloadMessage);
            }
        } else if (topic.startsWith(Topic.CLOUD_RPC_POST_TOPIC_PREFIX)) {
            /*
             * RPC消息，需要根据产品定义判断哪些是twoWay RPC消息.
             * 当为twoWay RPC消息时，需要截取topic最后的requestId进行response
             * response topic为v1/devices/me/rpc/response/$requestId
             */
            PayloadMessage payloadMessage = PayloadMessage.convertRPCMessagePM(topic, payload);
            String method = (String) payloadMessage.getProperty("method");
            JSONObject params = (JSONObject) payloadMessage.getProperty("params");
            Logger.i("method:" + method);
            Logger.i("paramsJSONObject:" + params);
            new ResponseRpc.Builder()
                    .topic(topic)
                    .method(method)
                    .params(params)
                    .build().handleOrResponse();
        } else if (topic.startsWith(Topic.CLOUD_PUSH_TOPIC_PREFIX)) { //云端推送的语聊消息
            new PushMsgRpc.Builder()
                    .topic(topic)
                    .params(jsonObject)
                    .build()
                    .handleOrResponse();
        } else if (topic.startsWith(Topic.CLIENT_RPC_RESPONSE_TOPIC_PREFIX)) {
            PayloadMessage payloadMessage = PayloadMessage.convertRPCMessagePM(topic, payload);
            /**
             * {
             *     "ERR_CODE":-103,
             *     "ERR_MSG":"Invalid RPC: RPC ID getLocation is not defined."
             * }
             */
//            //错误处理
            if (payloadMessage.hasProperty(PayloadMessage.ERR_CODE)) {
                int errCode = (int) payloadMessage.getProperty(PayloadMessage.ERR_CODE);
                String errMsg = (String) payloadMessage.getProperty(PayloadMessage.ERR_MSG);
                Logger.e("MessageCenter", "ERR_CODE->" + errCode + ",ERR_MSG->" + errMsg);
                return;
            }


            String requestId = topic.substring(topic.lastIndexOf("/") + 1);
            String responseMethod = (String) payloadMessage.getProperty(PayloadMessage.CLIENT_RPC_SERVER_RESPONSE_METHOD);
            if (responseMethod.equals(MqttConstants.ClientRpcMethod.GET_CODE)) {
                JSONObject data = (JSONObject) payloadMessage.getProperty(PayloadMessage.CLIENT_RPC_SERVER_RESPONSE_RESULT);
                DeviceCodeDTO deviceCodeDTO = JSONObject.toJavaObject(data, DeviceCodeDTO.class);
                DataHandleManager.getInstance().saveOrUpdateBindCode(deviceCodeDTO);
                return;
            }

            String cacheMethod = (String) GuavaCacheUtil.getIfPresent(requestId);
            if (cacheMethod != null) {
                //显示清除缓存
                GuavaCacheUtil.remove(requestId);
                JSONObject data = (JSONObject) payloadMessage.getProperty(PayloadMessage.CLIENT_RPC_SERVER_RESPONSE_RESULT);
                if (responseMethod.equals(MqttConstants.ClientRpcMethod.REQUEST_FRIEND)) { //交友
                    if(data.isEmpty()){
                        //交友请求已经提交
                        DataHandleManager.getInstance().handleMakeFriend(100);
                    }
                } else if(responseMethod.equals(MqttConstants.ClientRpcMethod.SEND_CHAT_MSG)){
                    String msgId = data.getString("msgId");
                    int msgTime = 0;
                    if(data.containsKey("msgTime")){
                        msgTime = data.getIntValue("msgTime");
                    }
                    DataHandleManager.getInstance().handleChatMsg(Integer.valueOf(requestId), msgId + "#" + msgTime);
                }
            }
        }
        //MqttService.getInstance().scheduleNextPing();
    }


    private boolean isTwoWayRpc(String method) {
        return !TextUtils.isEmpty(method) && (method.equals(MqttConstants.ServerRpcMethod.GET_DEVICE_STATUS));
    }

    @Override
    public boolean shouldHandle(String topic) {
        return topic.equals(Topic.DEVICE_ATTRIBUTES_TOPIC) || topic.startsWith(Topic.CLOUD_RPC_POST_TOPIC_PREFIX)
                || topic.startsWith(Topic.CLOUD_PUSH_TOPIC_PREFIX)
                || topic.equals(Topic.AUTH_TOPIC)
                || topic.startsWith(Topic.CLIENT_RPC_RESPONSE_TOPIC_PREFIX)
                || topic.startsWith(Topic.ATTRIBUTE_RESPONSE_PREFIX);
    }

    public interface DeviceSecretRegisterListener {

        void onDeviceSecretRegistered();
    }
}
